/// @Classname : HcTextEllipsis
/// @Author :
/// @Time : 2023-07-20 14:14
/// @Description : //todo

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:hc_ui/utils/hc_string_util.dart';

enum HcTextEllipsisPosition { start, center, end }

typedef HcTextEllipsisCallback = Future<bool?> Function(bool);

class HcTextEllipsis extends StatefulWidget {
  //需要展示的行数
  final int maxLines;

  //文字内容
  final String content;

  //展开的文字
  final String expandText;

  //折叠的文字
  final String collapseText;

  ///分隔符
  final String ellipsisDots;

  /// 文本的样式
  final TextStyle contentStyle;

  //按钮的 文字样式
  final TextStyle btnTextStyle;

  //点击按钮的回调
  final HcTextEllipsisCallback? callback;

  //分割符的位置
  final HcTextEllipsisPosition position;

  //是否展开
  final bool isExpand;

  //是否单独显示
  final bool separateShow;

  //是否展示拓展按钮
  final bool showEllipsisBtn;

  const HcTextEllipsis(
      {Key? key,
      this.isExpand = false,
      this.maxLines = 1,
      required this.content,
      this.expandText = "展开",
      this.collapseText = "收起",
      this.ellipsisDots = "...",
      this.position = HcTextEllipsisPosition.end,
      this.contentStyle = const TextStyle(color: Colors.black, fontSize: 16),
      this.callback,
      this.btnTextStyle = const TextStyle(
          color: Colors.blue, fontSize: 14, fontWeight: FontWeight.w500),
      this.separateShow = false,
      this.showEllipsisBtn = true})
      : super(key: key);

  @override
  State<HcTextEllipsis> createState() => _HcTextEllipsisState();
}

class _HcTextEllipsisState extends State<HcTextEllipsis> {
  //是否展开
  bool _isExpand = false;

  //组件的大小
  Size _viewSize = const Size(0, 0);

  //按钮组件的宽度
  double btnWidth = 0.0;

  //省略符号的宽度
  double dotWidth = 0.0;

  //文字高度
  double fontHeight = 0.0;

  //ellipsisLineWidth;
  double ellipsisLineWidth = 0.0;

  @override
  void initState() {
    super.initState();
    _isExpand = widget.isExpand;
  }

  @override
  void didUpdateWidget(covariant HcTextEllipsis oldWidget) {
    super.didUpdateWidget(oldWidget);
    _isExpand = widget.isExpand;
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, size) {
      //按钮的宽度
      btnWidth = HcStringUtil.boundingTextSize(
              context, widget.expandText, widget.btnTextStyle)
          .width;
      //文字的宽度与高度
      Size fontSize = HcStringUtil.boundingTextSize(
          context, widget.ellipsisDots, widget.contentStyle);
      dotWidth = fontSize.width;
      fontHeight = fontSize.height;
      //组件最大长度
      _viewSize = Size(size.maxWidth, size.maxHeight);
      //获取painter信息
      TextPainter painter = HcStringUtil.getTextInfo(
          context: context,
          text: widget.content,
          style: widget.contentStyle,
          maxLines: widget.maxLines,
          width: _viewSize.width);

      // 如果不满一行直接显示
      if (!painter.didExceedMaxLines) {
        return Text(widget.content, style: widget.contentStyle);
      }
      String result = "";
      String content = widget.content;
      switch (widget.position) {
        case HcTextEllipsisPosition.start:
          result = _buildEllipsisStartText(content, widget.maxLines);
          break;
        case HcTextEllipsisPosition.center:
          if (widget.maxLines == 1) {
            ellipsisLineWidth = _viewSize.width -
                (!widget.separateShow && widget.showEllipsisBtn
                    ? btnWidth
                    : 0) -
                dotWidth;
            int start = HcStringUtil.getTextInfo(
                    context: context,
                    text: content,
                    style: widget.contentStyle,
                    width: (ellipsisLineWidth ~/ 2).toDouble())
                .getPositionForOffset(
                    Offset((ellipsisLineWidth ~/ 2).toDouble(), 0))
                .offset;
            result = content.substring(0, start);
            result += widget.ellipsisDots;
            content = HcStringUtil.reverseString(content);
            int end = HcStringUtil.getTextInfo(
                    context: context,
                    text: content,
                    style: widget.contentStyle,
                    width:
                        ellipsisLineWidth - (ellipsisLineWidth ~/ 2).toDouble())
                .getPositionForOffset(Offset(
                    ellipsisLineWidth - (ellipsisLineWidth ~/ 2).toDouble(), 0))
                .offset;
            result += HcStringUtil.reverseString(content.substring(0, end));
          } else {
            double halfLine = (widget.maxLines ~/ 2).toDouble();
            result += _buildEllipsisEndText(content, widget.maxLines - halfLine,
                showEllipsis: false);
            result += _buildEllipsisStartText(content, halfLine);
          }
          break;
        case HcTextEllipsisPosition.end:
          result = _buildEllipsisEndText(content, widget.maxLines);
          break;
      }

      return RichText(
        text: TextSpan(
            text: _isExpand ? widget.content : result,
            style: widget.contentStyle,
            children: [if (widget.showEllipsisBtn) _ellipsisBtn()]),
      );
    });
  }

  InlineSpan _ellipsisBtn() {
    return TextSpan(
        text: _isExpand ? widget.collapseText : widget.expandText,
        style: widget.btnTextStyle,
        recognizer: TapGestureRecognizer()
          ..onTap = () async {
            bool isExpand = !_isExpand;
            if (widget.callback != null) {
              try {
                isExpand = await widget.callback!.call(_isExpand) ?? isExpand;
              } finally {}
            }
            setState(() {
              _isExpand = isExpand;
            });
          });
  }

  String _buildEllipsisStartText(content, maxLines) {
    String result = "";
    // 反转文字截取最后
    content = HcStringUtil.reverseString(content);
    // 获取文字展示宽度
    ellipsisLineWidth = _viewSize.width -
        (!widget.separateShow && widget.showEllipsisBtn ? btnWidth : 0) -
        (widget.maxLines == 1 ? dotWidth : 0);
    // 获取阶段位置
    int lastLineIndex = HcStringUtil.getTextInfo(
            context: context,
            text: content,
            style: widget.contentStyle,
            width: _viewSize.width)
        .getPositionForOffset(Offset(ellipsisLineWidth, 0))
        .offset;
    // 判断阶段位置展示的文字是否超过最大限度
    double resultWidth = HcStringUtil.boundingTextSize(context,
            content.substring(0, lastLineIndex), widget.contentStyle)
        .width;
    // 修正最大截取距离
    lastLineIndex =
        resultWidth > ellipsisLineWidth ? lastLineIndex - 1 : lastLineIndex;
    String temp = content.substring(0, lastLineIndex);
    if (maxLines > 1) {
      content = content.substring(lastLineIndex);
      if (maxLines > 2) {
        int centerIndex = HcStringUtil.getTextInfo(
                context: context,
                text: content,
                style: widget.contentStyle,
                width: _viewSize.width)
            .getPositionForOffset(
                Offset(_viewSize.width, fontHeight * (maxLines - 3)))
            .offset;
        temp += content.substring(0, centerIndex);

        content = content.substring(centerIndex);
      }
      int firstIndex = HcStringUtil.getTextInfo(
              context: context,
              text: content,
              style: widget.contentStyle,
              width: _viewSize.width - dotWidth)
          .getPositionForOffset(Offset(_viewSize.width - dotWidth, 0))
          .offset;
      temp += content.substring(0, firstIndex);
    }

    result = widget.ellipsisDots;
    result += HcStringUtil.reverseString(temp);
    return result;
  }

  String _buildEllipsisEndText(content, maxLines, {bool showEllipsis = true}) {
    String result = "";
    if (maxLines > 1) {
      int position = HcStringUtil.getTextInfo(
              context: context,
              text: content,
              style: widget.contentStyle,
              width: _viewSize.width)
          .getPositionForOffset(
              Offset(_viewSize.width, fontHeight * (maxLines - 2)))
          .offset;
      result = content.substring(0, position);
      content = content.substring(position);
    }
    ellipsisLineWidth = _viewSize.width -
        (showEllipsis && (!widget.separateShow && widget.showEllipsisBtn)
            ? btnWidth
            : 0) -
        dotWidth;
    int position = HcStringUtil.getTextInfo(
            context: context,
            text: content,
            style: widget.contentStyle,
            width: ellipsisLineWidth)
        .getPositionForOffset(Offset(ellipsisLineWidth, 0))
        .offset;
    result += content.substring(0, position);
    if (showEllipsis) {
      result += widget.ellipsisDots;
    }
    return result;
  }
}
